package com.atmilan.quartz.sync.pull.europe.service.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.atmilan.quartz.constant.enums.UpdateFlagEnum;
import com.atmilan.quartz.model.entity.europe.EuropeProductSku;
import com.atmilan.quartz.sync.pull.europe.mapper.EuropeProductSkuMapper;
import com.atmilan.quartz.sync.pull.europe.service.IEuropeProductSkuService;
import com.atmilan.quartz.utils.EuropeSendXmlUtil;
import com.atmilan.quartz.utils.EuropeUtil;
import com.atmilan.quartz.utils.STAXUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.StopWatch;
import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class EuropeProductSkuServiceImpl extends ServiceImpl<EuropeProductSkuMapper, EuropeProductSku> implements IEuropeProductSkuService {

    @Value("${europe.url}")
    private String url;

    @Value("${europe.username}")
    private String username;

    @Value("${europe.password}")
    private String password;

    @Autowired
    IEuropeProductSkuService europeProductSkuService;

    @Autowired
    EuropeProductSkuMapper europeProductSkuMapper;


    /**
     * 系统里所有的商品id，同步前先取一遍，方便判断更新还是添加操作
     */
    List<String> allSkuIdList = new ArrayList<String>();

    Lock lock = new ReentrantLock();

    @Override
    public Boolean getProductSku() {
        Boolean flag = false;
        if (lock.tryLock()){
            try{
                beforeProcess();
                StopWatch sw = new StopWatch("统计Europe商品SKU时间");
                flag = getProductSkuList(1,100,0,username,password,url,sw);
                sw.start("后置处理数据");
                afterProcess();

                if(sw.isRunning()) {
                    sw.stop();
                }
                log.warn(sw.prettyPrint());
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
        return flag;
    }

    public Boolean saveGoods(List<Map<String, Object>> europMapList){
        if(CollectionUtils.isEmpty(europMapList)){
            return false;
        }
        CountDownLatch latch = ThreadUtil.newCountDownLatch(europMapList.size());
        ExecutorService executorService = ThreadUtil.newExecutor(200);
        //解析xml文档
        List<EuropeProductSku> productSkuList = new ArrayList<>();
                for(Map<String,Object> map : europMapList){
                    List<HashMap<String,Object>> stockList = (List<HashMap<String, Object>>) map.get("Stock");
                    if(stockList != null && stockList.size() > 0){
                        stockList.forEach(item ->{
                            executorService.execute(new Runnable() {
                                @Override
                                public void run() {
                                    try {
                                        int qty = Integer.parseInt((String) item.get("Qty"));
                                        if(qty > 0){
                                            EuropeProductSku europeProductSku = new EuropeProductSku();
                                            // 设置更新标志, 最终为0 的都是本次未同步到的数据
                                            europeProductSku.setUpdateFlag(UpdateFlagEnum.add.getCode());
                                            getEuropeProductSku(qty,europeProductSku,map,item,stockList);
                                            //判断是更新还是新增
                                            if(allSkuIdList.contains(europeProductSku.getId())){//修改
                                                europeProductSku.setNewModifyTime(DateUtil.date());
                                                europeProductSkuService.updateById(europeProductSku);
                                            }else{//新增
                                                europeProductSku.setNewCreatedTime(DateUtil.date());
                                                europeProductSkuService.save(europeProductSku);
                                                allSkuIdList.add(europeProductSku.getId());
                                            }
                                            //System.out.println("EuropeProductSku:"+europeProductSku.toString());
                                            //productSkuList.add(europeProductSku);
                                        }
                                    }finally {
                                        latch.countDown();//当前线程调用此方法，则计数减一
                                    }
                                }
                            });
                        });
                    }
                }
        try {
            latch.await();
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        executorService.shutdown();//关闭线程池
        return true;
    }

    private List<EuropeProductSku> saveProductSku(List<Map<String, Object>> europMapList,List<String> allSkuIdList){
        Map<String, Object> map = europMapList.get(0);
        List<EuropeProductSku> list = new ArrayList<>();
        List<HashMap<String,Object>> stockList = (List<HashMap<String, Object>>) map.get("Stock");
        if(stockList != null && stockList.size() > 0){
            stockList.forEach(item ->{
                EuropeProductSku europeProductSku = new EuropeProductSku();
                europeProductSku.setUpdateFlag(UpdateFlagEnum.add.getCode());
                getEuropeProductSku(Integer.parseInt((String) item.get("Qty")),europeProductSku,map,item,stockList);
                //判断是新增还是更新
                if(allSkuIdList.contains(europeProductSku.getId())){//修改
                    europeProductSku.setNewModifyTime(DateUtil.date());
                    europeProductSkuService.updateById(europeProductSku);
                }else{//新增
                    europeProductSku.setNewCreatedTime(DateUtil.date());
                    europeProductSkuService.save(europeProductSku);
                    allSkuIdList.add(europeProductSku.getId());
                }
                list.add(europeProductSku);
            });
        }
        return list;
    }


    private EuropeProductSku getEuropeProductSku(int qty,EuropeProductSku europeProductSku,Map<String,Object> map,HashMap<String,Object> item,List<HashMap<String,Object>> stockList){
        europeProductSku.setId((String)map.get("ID") + "-" + stockList.indexOf(item));
        europeProductSku.setGoodsId(Integer.parseInt((String)map.get("ID")));
        europeProductSku.setSuperColor((String)map.get("SuperColor"));
        europeProductSku.setColor((String)map.get("Color"));
        europeProductSku.setFabric((String)map.get("Fabric"));
        europeProductSku.setComposition((String)map.get("Composition"));
        europeProductSku.setSizeAndFit((String)map.get("SizeAndFit"));
        europeProductSku.setMadeIn((String)map.get("MadeIn"));
        europeProductSku.setPictures(map.get("Pictures").toString());
        europeProductSku.setStock(map.get("Stock").toString());
        europeProductSku.setSize((String) item.get("Size"));
        europeProductSku.setQty(qty);
        europeProductSku.setSuk((String)map.get("Color") + "," + (String) item.get("Size"));
        String oldCreatedTime = (String) map.get("CreatedTime");
        if(oldCreatedTime != null && StringUtils.isNotBlank(oldCreatedTime)){
            if(oldCreatedTime.endsWith("AM")){
                oldCreatedTime = oldCreatedTime.replace(" AM","");
                try {
                    europeProductSku.setOldCreatedTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldCreatedTime));//map.get("CreatedTime")
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }else{
                oldCreatedTime = oldCreatedTime.replace(" PM","");
                try {
                    europeProductSku.setOldCreatedTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldCreatedTime));//map.get("CreatedTime")
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
        }else {
            europeProductSku.setOldCreatedTime(null);
        }
        String oldModifyTime = (String) map.get("ModifyTime");
        if(oldModifyTime != null && StringUtils.isNotBlank(oldModifyTime)){
            if(oldModifyTime.endsWith("AM")){
                oldModifyTime = oldModifyTime.replace(" AM","");
                try {
                    europeProductSku.setOldModifyTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldModifyTime));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }else{
                oldModifyTime = oldModifyTime.replace(" PM","");
                try {
                    europeProductSku.setOldModifyTime(new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse(oldModifyTime));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
        }else {
            europeProductSku.setOldModifyTime(null);
        }

        return  europeProductSku;
    }


    //递归查询所有商品数
    public Boolean getProductSkuList(Integer pageNum, Integer pageSize , Integer num, String username, String password, String url,StopWatch sw) throws Exception {
        Long start = System.currentTimeMillis();
        sw.start("远程抓取数据 第 " + pageNum + " 页");

        if(sw.isRunning()) {
            sw.stop();
        }
        String xml = "<tem:GetGoodsDetailListByPage>" + "<tem:PageNum>"+pageNum+"</tem:PageNum>"
                + "<tem:PageSize>"+pageSize+"</tem:PageSize>" + "</tem:GetGoodsDetailListByPage>";
        String sendMsg = EuropeSendXmlUtil.getSendMsg(xml);
        String respXml = EuropeUtil.getEuropeXml(username, password, url, sendMsg);
        List<Map<String, Object>> europMapList = STAXUtil.getEuropMapList(respXml, "GetGoodsDetailListByPage");
        log.warn("第{"+ pageNum +"}页共获取{"+europMapList.size()+"}条商品信息");
        sw.start("插入数据库 第 " + pageNum + " 页");
        Boolean b = saveGoods(europMapList);

        if(sw.isRunning()) {
            sw.stop();
        }
        log.warn("第{"+pageNum+"}页共耗时：{"+ (System.currentTimeMillis() - start)+"}");
        if(europMapList.size() > 0){//不是最后一页，继续查询
            pageNum ++;
            num += pageSize;
            //System.out.println("pageNum:"+pageNum+"----------------------------------num:"+num+"-----Date"+new Date());
            getProductSkuList(pageNum,pageSize,num,username,password,url,sw);
        }else{
            //是最后一页
            num += europMapList.size();
            //System.out.println("pageNum:"+pageNum+"----------------------------------num:"+num+"-----Date"+new Date());
        }
        return b;
    }

    @Override
    public List<EuropeProductSku> getEuropeProductSkuListByGoodsId(String goodsId) {
        QueryWrapper<EuropeProductSku> qw = new QueryWrapper<>();
        qw.lambda().eq(EuropeProductSku::getGoodsId,goodsId);
        return this.list(qw);
    }

    @Override
    public List<EuropeProductSku> getEuropeProductSku(String goodsId,List<String> allSkuIdList) {
        String xml = "<tem:GetGoodsDetailByGoodsID>" + "<tem:GoodsID>"+goodsId+"</tem:GoodsID>"
                + "</tem:GetGoodsDetailByGoodsID>";
        //调用接口
        String sendMsg = EuropeSendXmlUtil.getSendMsg(xml);
        String respXml = null;
        try {
            respXml = EuropeUtil.getEuropeXml(username, password, url, sendMsg);
            List<Map<String, Object>> europMapList = STAXUtil.getEuropMapList(respXml, "GetGoodsDetailByGoodsID");
            //解析数据
            List<EuropeProductSku> productSkuList = saveProductSku(europMapList, allSkuIdList);
            return  productSkuList;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public List<String> findAllSkuIds() {
        List<Object> list = europeProductSkuMapper.selectObjs(new QueryWrapper<EuropeProductSku>().select("id"));
        return list == null? new ArrayList<String>():list.stream().map(o->o.toString()).collect(Collectors.toList());
    }

    private void beforeProcess(){
        allSkuIdList.clear();
        allSkuIdList = this.findAllSkuIds();
        List<EuropeProductSku> list = this.list();
        list.forEach(skus ->{
            skus.setUpdateFlag(UpdateFlagEnum.un_modify.getCode());
            this.updateById(skus);
        });
        //europeProductSkuService.update(Wrappers.<EuropeProductSku>lambdaUpdate().set(EuropeProductSku::getUpdateFlag, UpdateFlagEnum.un_modify.getCode()));
    }
    // 同步后 做什么？ 要清数据吗?
    private void afterProcess(){
        allSkuIdList.clear();
    }

    @Override
    public void deleteAll() {
        europeProductSkuMapper.deleteAll();
    }
    
    @Override
    public void copyAll() {
        europeProductSkuMapper.deleteProductSkuBack();
        europeProductSkuMapper.copyProductSkuBack();
    }

}
